// Ternary Search Tree Implementation for C# 

using System;
using System.Collections;

namespace Raxxla.DayBreak.Core.Collections
{
	/// <summary>
	/// Defines a <see cref="TstDictionary"/> tree traverser object.
	/// </summary>
	/// <remarks>
	/// <para>
	/// This class can be used to traverse the ternary tree. It defines two events:
	/// TreeEntry and DiscoverEntry.
	/// </para>
	/// </remarks>
	public class TstTraverser
	{
		/// <summary>
		/// Default constructor
		/// </summary>
		public TstTraverser()
		{}

		/// <summary>
		/// Tarverses the ternary search tree nodes of <paramref name="dic"/>.
		/// </summary>
		/// <param name="dic">Tree to explore</param>
		/// <exception cref="ArgumentNullException"><paramref name="dic"/> is null.</exception>
        public void Traverse( TstDictionary<ValueType> dic )
        {
			if (dic==null)
				throw new ArgumentNullException("dic");
			Traverse(dic.Root);
		}

		///<summary>Event called when a node is integrated into the traversed tree.</summary>
        public event TstDictionaryEntryEventHandler<ValueType> TreeEntry;

        /// <summary>
		/// Raises the <see cref="TstTraverser.TreeEntry"/> event.
		/// </summary>
		/// <param name="p">tst node added to the tree</param>
        protected virtual void OnTreeEntry( TstDictionaryEntry<ValueType> p )
        {
			if (TreeEntry!=null)
				TreeEntry(this,
                    new TstDictionaryEntryEventArgs<ValueType>( p )
                    );
		}

		///<summary>Event called when a node is discovered but not yet in the explore tree.</summary>
        public event TstDictionaryEntryEventHandler<ValueType> LowChild;

        /// <summary>
		/// Raises the <see cref="TstTraverser.HighChild"/> event.
		/// </summary>
		/// <param name="p">high child about to be added to the tree</param>	
        protected virtual void OnLowChild( TstDictionaryEntry<ValueType> p )
        {
			if (LowChild!=null)
				LowChild(this,
                    new TstDictionaryEntryEventArgs<ValueType>( p )
                    );
		}
		
		///<summary>Event called when a node is discovered but not yet in the explore tree.</summary>
        public event TstDictionaryEntryEventHandler<ValueType> EqChild;

        /// <summary>
		/// Raises the <see cref="TstTraverser.HighChild"/> event.
		/// </summary>
		/// <param name="p">high child about to be added to the tree</param>	
        protected virtual void OnEqChild( TstDictionaryEntry<ValueType> p )
        {
			if (EqChild!=null)
				EqChild(this,
                    new TstDictionaryEntryEventArgs<ValueType>( p )
                    );
		}

		///<summary>Event called when a node is discovered but not yet in the explore tree.</summary>
        public event TstDictionaryEntryEventHandler<ValueType> HighChild;

        /// <summary>
		/// Raises the <see cref="TstTraverser.HighChild"/> event.
		/// </summary>
		/// <param name="p">high child about to be added to the tree</param>	
        protected virtual void OnHighChild( TstDictionaryEntry<ValueType> p )
        {
			if (HighChild!=null)
				HighChild(this,
                    new TstDictionaryEntryEventArgs<ValueType>( p )
                    );
		}

		/// <summary>
		/// Traverses the <paramref name="p"/> sub-tree.
		/// </summary>
		/// <param name="p">node to traverse.</param>
        protected void Traverse( TstDictionaryEntry<ValueType> p )
        {
			if (p==null)
				return;

			OnTreeEntry(p);

			OnLowChild(p.LowChild);
			Traverse(p.LowChild);
			OnEqChild(p.EqChild);
			Traverse(p.EqChild);
			OnHighChild(p.HighChild);
			Traverse(p.HighChild);
		}
		
 	}
}
